#!/bin/bash

gl_base_path=$(
    cd "$(dirname "$0")" || exit 1
    pwd
)

gl_dir="${gl_base_path}/cert"
gl_subj="/CN=*.com/O=seli/OU=opell"
gl_cert_dirs=("server-rpc" "server-exc" "server-plugin" "server-to-plugin-java-fabric2" "plugin-to-server-java-fabric2" "plugin-java-fabric2" "console" "sdk")
gl_ecdsa_curve="secp384r1"
gl_ecdsa_alg="sha256"

function gen_rsa() {
    if [ -d "${gl_dir}" ]; then
        confirm "${gl_dir} existed, override?"
        local confirm_result=$?
        if [ $confirm_result -ne 0 ]; then
            return 0
        fi
        rm -rf ${gl_dir}
    fi

    mkdir -p ${gl_dir}

    # generate ca cert
    gen_rsa_ca

    # generate ssl cert
    for cert_dir in ${gl_cert_dirs[@]};do
        gen_rsa_ssl $cert_dir
    done

    echo "rsa cert generate success!"
}

function gen_rsa_ca() {
    openssl genrsa -out ${gl_dir}/rsa_ca.key 4096
    openssl req -new -x509 -days 3650 -subj "${gl_subj}" -key ${gl_dir}/rsa_ca.key -out ${gl_dir}/ca.crt
    openssl pkcs8 -topk8 -in ${gl_dir}/rsa_ca.key -out ${gl_dir}/ca.key -nocrypt
    rm -rf ${cert_dir}/rsa_ca.key
}

function gen_rsa_ssl() {
    local cert_dir=${gl_dir}/$1
    if [ -d "${cert_dir}" ]; then
        confirm "${cert_dir} existed, override?"
        local confirm_result=$?
        if [ $confirm_result -ne 0 ]; then
            return 0
        fi
        rm -rf ${cert_dir}
    fi

    mkdir -p ${cert_dir}

    openssl genrsa -out ${cert_dir}/rsa_ssl.key 4096
    openssl req -new -sha256 -subj "${gl_subj}" -key ${cert_dir}/rsa_ssl.key -out ${cert_dir}/ssl.csr
    openssl x509 -req -days 3650 -sha256 -CA ${gl_dir}/ca.crt -CAkey ${gl_dir}/ca.key -CAcreateserial \
        -in ${cert_dir}/ssl.csr -out ${cert_dir}/ssl.crt -extensions v4_req
    openssl pkcs8 -topk8 -in ${cert_dir}/rsa_ssl.key -out ${cert_dir}/ssl.key -nocrypt
    rm -rf ${cert_dir}/rsa_ssl.key

    cp ${gl_dir}/ca.crt ${cert_dir}/
}

function gen_ecdsa() {
    if [ -d "${gl_dir}" ]; then
        confirm "${gl_dir} existed, override?"
        local confirm_result=$?
        if [ $confirm_result -ne 0 ]; then
            return 0
        fi
        rm -rf ${gl_dir}
    fi

    mkdir -p ${gl_dir}

    # generate ca cert
    gen_ecdsa_ca

    # generate ssl cert
    for cert_dir in ${gl_cert_dirs[@]};do
        gen_ecdsa_ssl $cert_dir
    done

    echo "rsa cert generate success!"
}

function gen_ecdsa_ca() {
    openssl ecparam -out ${gl_dir}/ecdsa_ca.key -name ${gl_ecdsa_curve} -genkey
    openssl req -new -x509 -days 3650 -subj "${gl_subj}" -key ${gl_dir}/ecdsa_ca.key -out ${gl_dir}/ca.crt
    openssl pkcs8 -topk8 -in ${gl_dir}/ecdsa_ca.key -out ${gl_dir}/ca.key -nocrypt
    rm -rf ${cert_dir}/ecdsa_ca.key
}

function gen_ecdsa_ssl() {
    local cert_dir=${gl_dir}/$1
    if [ -d "${cert_dir}" ]; then
        confirm "${cert_dir} existed, override?"
        local confirm_result=$?
        if [ $confirm_result -ne 0 ]; then
            return 0
        fi
        rm -rf ${cert_dir}
    fi

    mkdir -p ${cert_dir}

    openssl ecparam -out ${cert_dir}/rsa_ssl.key -name ${gl_ecdsa_curve} -genkey
    openssl req -new -sha256 -subj "${gl_subj}" -key ${cert_dir}/rsa_ssl.key -out ${cert_dir}/ssl.csr
    openssl x509 -req -days 3650 -sha256 -CA ${gl_dir}/ca.crt -CAkey ${gl_dir}/ca.key -CAcreateserial \
        -in ${cert_dir}/ssl.csr -out ${cert_dir}/ssl.crt -extensions v4_req
    openssl pkcs8 -topk8 -in ${cert_dir}/rsa_ssl.key -out ${cert_dir}/ssl.key -nocrypt
    rm -rf ${cert_dir}/rsa_ssl.key

    cp ${gl_dir}/ca.crt ${cert_dir}/
}

function gengm() {
    echo "gen gm."
}

function usage() {
    echo -e "Usage: bash start"
    cat <<EOF
-------------------------------------------------------------
gen
    bash gencert.sh gen_rsa                        生成rsa证书（包括：ca、ssl）
    bash crosschain.sh gen_rsa_ssl                  生成rsa ssl证书
    bash gencert.sh gen_ecdsa                      生成ecdsa证书（包括：ca、ssl）
    bash crosschain.sh gen_ecdsa_ssl                生成ecdsa ssl证书
EOF
    echo "this is usage."
}

function confirm() {
    echo -en "tip:"
    echo -e $1
    read -r -p 'continue? [Yes/No]' input
    case $input in
    [yY][eE][sS] | [yY])
        return 0
        ;;
    [nN][oO] | [nN])
        return 1
        ;;
    *)
        echo "Invalid input!"
        exit 1
        ;;
    esac
}

main() {
    case "$1" in
        (gen_rsa)
            gen_rsa
            ;;
        (gen_rsa_ssl)
            gen_rsa_ssl $2
            ;;
        (gen_ecdsa)
            gen_ecdsa
            ;;
        (gen_ecdsa_ssl)
            gen_ecdsa_ssl $2
            ;;
        (gm)
            gengm
            ;;
        (help)
            usage
            exit 0
            ;;
        (*)
            usage
            exit 0
            ;;
    esac
}

main $@
